//
//  LBNetworkManager.m
//  LBBase
//
//  Created by Gary on 15/7/1.
//  Copyright (c) 2015年 Lebo. All rights reserved.
//

#import "LBNetworkManager.h"
#import "LBBaseNetworkManager.h"
#import "LBRequestParameter.h"
#import "CommonDefine.h"
#import "ConfigDefine.h"
#import "Common.h"

@interface LBNetworkManager() {
    LBBaseNetworkManager *_manager;
}
@end

@implementation LBNetworkManager

- (instancetype)init {
    self = [super init];
    if (self) {
        //self.isIdle = YES;
        _retryRequestTasks = [[NSMutableArray alloc] init];
        _manager = [[LBBaseNetworkManager alloc] init];
    }
    return self;
}

- (void)dealloc {
    [_requestTasks cancelAll];
    [_requestTasks removeAll];
    [_retryRequestTasks removeAllObjects];
}

#pragma mark - setter/getter

+ (void)updateRequestCookies {
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:[Common baseServerURL]]];
    if (cookies) {
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookies];
        [[NSUserDefaults standardUserDefaults] setObject:data forKey:kUSKeyCurrentToken];
    }
}

+ (void)setRequestCookies:(LBBaseNetworkManager*)manager urlString:(NSString*)urlString {
    manager.requestSerializer.HTTPShouldHandleCookies = YES;
    NSData *cookiesdata = [[NSUserDefaults standardUserDefaults] objectForKey:kUSKeyCurrentToken];
    if([cookiesdata length]) {
        NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesdata];
        for (NSHTTPCookie *cookie in cookies) {
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
        }
    }
}

- (void)addRetryRequestTask:(AFHTTPRequestOperation*)operation param:(NSDictionary*)dic {
    @synchronized(_retryRequestTasks) {
        //在已有的列表中查找，若已存在，则不需要再次添加
        BOOL find = NO;
        for (LBRequestParameter *param in self.retryRequestTasks) {
            if (operation == param.operation) {
                find = YES;
                break;
            }
        }
        if (!find) {
            //将参数实体保存起来
            [_retryRequestTasks addObject:[LBRequestParameter parameter:operation
                                                                    url:nil
                                                                 header:nil
                                                                   body:[NSMutableDictionary dictionaryWithDictionary:dic]]];
        }
    }
}

- (void)removeRetryRequestTask:(AFHTTPRequestOperation*)operation {
    @synchronized(_retryRequestTasks) {
        for (NSInteger i = 0; i < _retryRequestTasks.count; i++) {
            LBRequestParameter *param = [_retryRequestTasks objectAtIndex:i];
            if (param.operation == operation) {
                [_retryRequestTasks removeObjectAtIndex:i];
                return;
            }
        }
    }
}

- (LBRequestTaskQueue *)getRequestTasks {
    if (!_requestTasks) {
        _requestTasks = [[LBRequestTaskQueue alloc] init];
    }
    return _requestTasks;
}

/**
 *  请求数据:get方法
 *
 *  @param urlString url地址，除去前缀的部分。前缀在LBBaseNetworkManager初始化时设置了。
 *  @param parms     请求参数
 *  @param success   成功的响应块
 *  @param fail      失败的响应块
 */
- (void)getDataWithUrl:(NSString *)urlString
                params:(NSDictionary *)params
            withCookie:(BOOL)withCookie {
    NSDictionary *reqData = [params objectForKey:kNetworkRequestData];
    LogInfo(@"nm tag: %d\nget request data: \%@", self.tag, reqData);
    
    if (withCookie) {
        [LBNetworkManager setRequestCookies:_manager urlString:urlString];
    }
    _manager.responseSerializer.acceptableContentTypes = [_manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
    _manager.requestSerializer.timeoutInterval = kNetworkRequestTimeoutInterval;
   __block __weak LBNetworkManager *weakSelf = self;
    AFHTTPRequestOperation *operationReq = [_manager GET:urlString
                                             parameters:reqData
                                                success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:responseObject, kNetworkResponseData, operation.userInfo[kNetworkRequestInfo], kNetworkRequestInfo, nil];
                                                    [weakSelf didReceiveNetData:dic reqOperation:operation];
                                                    [weakSelf.requestTasks removeTask:operation];
                                                    [weakSelf removeRetryRequestTask:operation];
                                                }
                                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                    [weakSelf didFailWithNetRequest:operation error:error];
                                                    [weakSelf.requestTasks removeTask:operation];
                                                }];
    
    // 记录请求名，当请求成功或失败返回的时候，可以知道是哪个请求。
    NSDictionary *reqInfo = [params objectForKey:kNetworkRequestInfo];
    operationReq.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[reqData objectForKey:kNetReqParamServiceKey], kNetworkRequestName, reqInfo, kNetworkRequestInfo, nil];
    [self.requestTasks addTask:operationReq];
    [self addRetryRequestTask:operationReq param:params];
}

/**
 *  请求数据:get xml方法
 *
 *  @param urlString url地址，除去前缀的部分。前缀在LBBaseNetworkManager初始化时设置了。
 *  @param parms     请求参数
 *  @param success   成功的响应块
 *  @param fail      失败的响应块
 */
- (void)getXmlDataWithUrl:(NSString *)urlString
            params:(NSDictionary *)params
               withCookie:(BOOL)withCookie {
    _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/xml"];
    _manager.requestSerializer.timeoutInterval = kNetworkRequestTimeoutInterval;
    if (withCookie) {
        [LBNetworkManager setRequestCookies:_manager urlString:urlString];
    }
    
    __block __weak LBNetworkManager *weakSelf = self;
    AFHTTPRequestOperation *operationReq = [_manager GET:urlString
                                             parameters:params
                                                success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                    [weakSelf didReceiveNetData:responseObject reqOperation:operation];
                                                    [weakSelf.requestTasks removeTask:operation];
                                                }
                                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                    [weakSelf didFailWithNetRequest:operation error:error];
                                                    [weakSelf.requestTasks removeTask:operation];
                                                }];
    
    // 记录一下请求名字，当请求成功或失败返回的时候，可以知道是哪个请求。
    operationReq.userInfo = [NSDictionary dictionaryWithObject:urlString forKey:kNetworkRequestName];
    [self.requestTasks addTask:operationReq];
}

/**
 *  请求数据:json post方法
 *
 *  @param urlString url地址，除去前缀的部分。前缀在LBBaseNetworkManager初始化时设置了。
 *  @param parms     请求参数
 *  @param success   成功的响应块
 *  @param fail      失败的响应块
 */
- (void)postJsonDataWithUrl:(NSString*)urlString
                     params:(NSDictionary*)params
                 withCookie:(BOOL)withCookie {
    NSDictionary *reqData = [params objectForKey:kNetworkRequestData];
    LogInfo(@"nm tag: %d\npost request data: \%@", self.tag, reqData);
    
    /*
    //纯JSON结构发送
    //manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"];
    //manager.requestSerializer = [AFJSONRequestSerializer serializer];
    */
    
    _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
    _manager.requestSerializer = [AFHTTPRequestSerializer serializer];   //传统的发送POST数据方式
    _manager.requestSerializer.timeoutInterval = kNetworkRequestTimeoutInterval;
    
    _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    //manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
    
    //if (withCookie) {
    //    [LBNetworkManager setRequestCookies:manager urlString:urlString];
    //}
    
    __block __weak LBNetworkManager *weakSelf = self;
    AFHTTPRequestOperation *operationReq = [_manager POST:urlString
                                              parameters:reqData
                                                 success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                     NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:responseObject, kNetworkResponseData, operation.userInfo[kNetworkRequestInfo], kNetworkRequestInfo, nil];
                                                     [weakSelf didReceiveNetData:dic reqOperation:operation];
                                                     [weakSelf.requestTasks removeTask:operation];
                                                     [weakSelf removeRetryRequestTask:operation];
                                                 }
                                                 failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                     [weakSelf didFailWithNetRequest:operation error:error];
                                                     [weakSelf.requestTasks removeTask:operation];
                                                 }];
    // 记录请求名，当请求成功或失败返回的时候，可以知道是哪个请求。
    //operationReq.userInfo = [NSDictionary dictionaryWithObject:urlString forKey:kNetworkRequestName];
    NSDictionary *reqInfo = [params objectForKey:kNetworkRequestInfo];
    operationReq.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[reqData objectForKey:kNetReqParamServiceKey], kNetworkRequestName, reqInfo, kNetworkRequestInfo, nil];
    [self.requestTasks addTask:operationReq];
    [self addRetryRequestTask:operationReq param:params];
}

/**
 *  请求数据:xml post方法
 *
 *  @param urlString url地址，除去前缀的部分。前缀在LBBaseNetworkManager初始化时设置了。
 *  @param xmlString     xml字符串
 *  @param encoding   编码方式
 */
- (void)postXmlDataWithUrl:(NSString *)urlString
             params:(NSDictionary *)params
                 xmlString:(NSString *)xmlString
                  encoding:(NSString*)encoding
                withCookie:(BOOL)withCookie {
    _manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/xml"];
    _manager.requestSerializer.timeoutInterval = kNetworkRequestTimeoutInterval;
    if (withCookie) {
        [LBNetworkManager setRequestCookies:_manager urlString:urlString];
    }
    
    //将参数的字典转换为字符串
    NSString *str;
    if (params) {
        str = [NSString stringWithFormat:@"%@?%@", urlString, [Common URLEncodedStringFromKeyAndValue:nil value:params]];
    } else {
        str = urlString;
    }
    
    //初始化网络请求
    NSURL *url = [NSURL URLWithString:[[NSURL URLWithString:str relativeToURL:_manager.baseURL] absoluteString]];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    request.allowsCellularAccess = _manager.requestSerializer.allowsCellularAccess;
    request.cachePolicy = _manager.requestSerializer.cachePolicy;
    request.HTTPShouldHandleCookies = _manager.requestSerializer.HTTPShouldHandleCookies;
    request.HTTPShouldUsePipelining = _manager.requestSerializer.HTTPShouldUsePipelining;
    request.networkServiceType = _manager.requestSerializer.networkServiceType;
    request.timeoutInterval = _manager.requestSerializer.timeoutInterval;
    
    //定义header
    request.HTTPMethod = @"POST";
    [request setValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"];
    NSString *charset = @"utf-8";
    NSStringEncoding enc = NSUTF8StringEncoding;
    if ([[encoding lowercaseString] isEqualToString:@"gbk"]) {
        charset = @"gbk";
        enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    }
    [request setValue:charset forHTTPHeaderField:@"charset"];
    
    //定义body
    [request setHTTPBody:[xmlString dataUsingEncoding:enc]];
    
    __block __weak LBNetworkManager *weakSelf = self;
    AFHTTPRequestOperation *operationReq =
    [_manager HTTPRequestOperationWithRequest:request
                                     success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                         [weakSelf didReceiveNetData:responseObject reqOperation:operation];
                                         [weakSelf.requestTasks removeTask:operation];
                                     }
                                     failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                         [weakSelf didFailWithNetRequest:operation error:error];
                                         [weakSelf.requestTasks removeTask:operation];
                                     }];
    [_manager.operationQueue addOperation:operationReq];
    // 记录一下请求名字，当请求成功或失败返回的时候，可以知道是哪个请求。
    operationReq.userInfo = [NSDictionary dictionaryWithObject:urlString forKey:kNetworkRequestName];
    [self.requestTasks addTask:operationReq];
}

- (void)postUploadWithUrl:(NSString*)urlString
                   params:(NSDictionary*)params
               withCookie:(BOOL)withCookie {
    NSDictionary *reqData = [params objectForKey:kNetworkRequestData];
    LogInfo(@"reqData: \%@", reqData);
    NSMutableDictionary *reqDic = [NSMutableDictionary dictionaryWithDictionary:reqData];
    NSArray *arr = reqDic[kNetworkUploadArray];
    NSArray *uploadArr = (arr && [arr isKindOfClass:[NSArray class]]) ? arr.copy : nil;
    [reqDic removeObjectForKey:kNetworkUploadArray];
    LogInfo(@"post request data: \%@", reqDic);
    
    /*
     //纯JSON结构发送
     //manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"];
     //manager.requestSerializer = [AFJSONRequestSerializer serializer];
     */
    
    _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
    _manager.requestSerializer = [AFHTTPRequestSerializer serializer];   //传统的发送POST数据方式
    _manager.requestSerializer.timeoutInterval = kNetworkRequestTimeoutInterval;
    
    _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    //manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
    
    //if (withCookie) {
    //    [LBNetworkManager setRequestCookies:manager urlString:urlString];
    //}
    
    __block __weak LBNetworkManager *weakSelf = self;
    AFHTTPRequestOperation *operationReq = [_manager POST:urlString
                                              parameters:reqDic
                               constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                                   if (!IsEmpty(uploadArr)) {
                                       for (NSDictionary *dic in uploadArr) {
                                           [formData appendPartWithFileData:[dic[kNetworkUploadFileData] pointerValue]
                                                                       name:dic[kNetworkUploadParam]
                                                                   fileName:dic[kNetworkUploadFileName]
                                                                   mimeType:dic[kNetworkUploadFileType]];
                                       }
                                   }
                               }
                                                 success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                     NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:responseObject, kNetworkResponseData, operation.userInfo[kNetworkRequestInfo], kNetworkRequestInfo, nil];
                                                     [weakSelf didReceiveNetData:dic reqOperation:operation];
                                                     [weakSelf.requestTasks removeTask:operation];
                                                     [weakSelf removeRetryRequestTask:operation];
                                                 }
                                                 failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                     [weakSelf didFailWithNetRequest:operation error:error];
                                                     [weakSelf.requestTasks removeTask:operation];
                                                 }];
    // 记录请求名，当请求成功或失败返回的时候，可以知道是哪个请求。
    //operationReq.userInfo = [NSDictionary dictionaryWithObject:urlString forKey:kNetworkRequestName];
    NSDictionary *reqInfo = [params objectForKey:kNetworkRequestInfo];
    operationReq.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[reqData objectForKey:kNetReqParamServiceKey], kNetworkRequestName, reqInfo, kNetworkRequestInfo, nil];
    [self.requestTasks addTask:operationReq];
    [self addRetryRequestTask:operationReq param:params];
}

#pragma mark - receive

- (void)didReceiveNetData:(id)data reqOperation:(AFHTTPRequestOperation *)operation {
    //获取请求的方法名，来判断是哪个请求的响应。
    NSString *requestMethodName = operation.userInfo[kNetworkRequestName];
    
    //LogDebug(@"Request Name: %@, Data: %@", requestMethodName, data);
    if (self.delegate) {
        [self.delegate didReceiveNetData:data requestName:requestMethodName];
    }
}

- (void)didFailWithNetRequest:(AFHTTPRequestOperation *)operation error:(NSError *)error {
    NSString *message = nil;
    switch (error.code) {
        case -1004: {
            message = [Common getLocalStr:@"NetworkResponseFailed"];
            break;
        }
            
        case -1001: {
            message = [Common getLocalStr:@"NetworkRequestTimeout"];
            break;
        }
            
        case -1011: {
            break;
        }
            
        case -1016: {
            //该操作为短时间内多次请求产生的错误，应予以忽略
            return;
            break;
        }
        
        default: {
            //此处添加服务器Token过期的返回判断，以便进行自动登录
            //if ([error.localizedDescription isEqualToString:@"Request failed: client error (499)"]) {
            //    LogInfo(@"error: %@", error.localizedDescription);
            //    [Common loginWithCurrentUser];  //token过期，自动重新登录
            //    return;
            //}
            //message = [Common getLocalStr:@"NetworkRequestUnusual"];
            break;
        }
    }
    
    if (!message) {
        message = [error localizedDescription];
    }
    
    NSString *requestMethodName = operation.userInfo[kNetworkRequestName];
    [self removeRetryRequestTask:operation];
    LogWarn(@"requeset failed for: %@, service: %@, error.code: %d, error.localizedDescription: %@", [Common baseServerURL], requestMethodName, (int)error.code, error.localizedDescription);
    
    if (self.delegate) {
        //封装新的NSError，包含了常见的网络错误
        NSError *newError = [NSError errorWithDomain:error.domain code:error.code userInfo:[NSDictionary dictionaryWithObject:message forKey:kNetworkResponseErrorMessageKey]];
        [self.delegate didFailWithNetRequest:[NSDictionary dictionaryWithObjectsAndKeys:newError, kNetworkResponseData, operation.userInfo[kNetworkRequestInfo], kNetworkRequestInfo, nil] requestName:requestMethodName];
    }
}

@end
